Nach Angaben der Weltgesundheitsorganisation (WHO) ist der Schlaganfall die zweithäufigste Todesursache weltweit und für etwa 11% der Gesamttodesfälle verantwortlich.
Dieser Datensatz wird verwendet, um vorherzusagen, ob ein Patient wahrscheinlich einen Schlaganfall erleiden wird, basierend auf Eingabeparametern wie Geschlecht, Alter, verschiedene Krankheiten und Raucherstatus (insgesamt 11 klinische Merkmale).
Es soll ein Frühwarnsystem erstellt werden, das anhand der im Datensatz erfassten klinischen Merkmale das Risiko eines Schlaganfalls prognostizieren kann. Das System soll Ärzte in Ihrer Arbeit unterstützen.
Download Stroke Prediction Dataset
Use only for educational purposes
import pandas as pd
import plotly.express as px
import plotly as pt
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv("healthcare-dataset-stroke-data.csv")
df.head()
| id | gender | age | hypertension | heart_disease | ever_married | work_type | Residence_type | avg_glucose_level | bmi | smoking_status | stroke | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 9046 | Male | 67.0 | 0 | 1 | Yes | Private | Urban | 228.69 | 36.6 | formerly smoked | 1 |
| 1 | 51676 | Female | 61.0 | 0 | 0 | Yes | Self-employed | Rural | 202.21 | NaN | never smoked | 1 |
| 2 | 31112 | Male | 80.0 | 0 | 1 | Yes | Private | Rural | 105.92 | 32.5 | never smoked | 1 |
| 3 | 60182 | Female | 49.0 | 0 | 0 | Yes | Private | Urban | 171.23 | 34.4 | smokes | 1 |
| 4 | 1665 | Female | 79.0 | 1 | 0 | Yes | Self-employed | Rural | 174.12 | 24.0 | never smoked | 1 |
df.shape
(5110, 12)
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5110 entries, 0 to 5109 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 5110 non-null int64 1 gender 5110 non-null object 2 age 5110 non-null float64 3 hypertension 5110 non-null int64 4 heart_disease 5110 non-null int64 5 ever_married 5110 non-null object 6 work_type 5110 non-null object 7 Residence_type 5110 non-null object 8 avg_glucose_level 5110 non-null float64 9 bmi 4909 non-null float64 10 smoking_status 5110 non-null object 11 stroke 5110 non-null int64 dtypes: float64(3), int64(4), object(5) memory usage: 479.2+ KB
Die Spalten mit dem Datentyp object werden im Data Preprocessing passend für die eingesetzten Machine Learning Verfahren in float umgewandelt.
(siehe Stroke.py, function init_data(...))
Die Spalte id liefert keine wertvolle Information und wird daher entfernt.
df.drop(columns=['id'], inplace=True)
df.describe()
| age | hypertension | heart_disease | avg_glucose_level | bmi | stroke | |
|---|---|---|---|---|---|---|
| count | 5110.000000 | 5110.000000 | 5110.000000 | 5110.000000 | 4909.000000 | 5110.000000 |
| mean | 43.226614 | 0.097456 | 0.054012 | 106.147677 | 28.893237 | 0.048728 |
| std | 22.612647 | 0.296607 | 0.226063 | 45.283560 | 7.854067 | 0.215320 |
| min | 0.080000 | 0.000000 | 0.000000 | 55.120000 | 10.300000 | 0.000000 |
| 25% | 25.000000 | 0.000000 | 0.000000 | 77.245000 | 23.500000 | 0.000000 |
| 50% | 45.000000 | 0.000000 | 0.000000 | 91.885000 | 28.100000 | 0.000000 |
| 75% | 61.000000 | 0.000000 | 0.000000 | 114.090000 | 33.100000 | 0.000000 |
| max | 82.000000 | 1.000000 | 1.000000 | 271.740000 | 97.600000 | 1.000000 |
df.isnull().sum()
gender 0 age 0 hypertension 0 heart_disease 0 ever_married 0 work_type 0 Residence_type 0 avg_glucose_level 0 bmi 201 smoking_status 0 stroke 0 dtype: int64
Im Datensatz fehlen in der Spalte bmi Werte, die im Data Preprocessing durch einen KNNImputer ergänzt werden
(siehe Stroke.py, function prepare_data(...))
df.duplicated().sum()
0
Der Datensatz enthält (unter Ausschluss der Spalte id) keine Duplikate.
df['gender'].unique()
array(['Male', 'Female', 'Other'], dtype=object)
df['smoking_status'].unique()
array(['formerly smoked', 'never smoked', 'smokes', 'Unknown'],
dtype=object)
df['Residence_type'].unique()
array(['Urban', 'Rural'], dtype=object)
df['work_type'].unique()
array(['Private', 'Self-employed', 'Govt_job', 'children', 'Never_worked'],
dtype=object)
df['ever_married'].unique()
array(['Yes', 'No'], dtype=object)
Im Data Preprocessing werden die Spalten mit kategorischen Daten transformiert.
(siehe Stroke.py, function init_data(...))
Die Einheiten der verschiedenen Merkmale widersprechen sich nicht.
Wir untersuchen, wie die Merkmale mit der Zielspalte korrelieren (Patienten mit/ohne Schlaganfall), um einen ersten Eindruck von den Daten zu erhalten.
ratio = df[df['stroke'] == 1].shape[0] / df.shape[0]
print(f'{ratio * 100:.2f}%')
4.87%
fig = px.pie(df,
names='stroke',
title=f'<b>Anteil an Patienten mit Schlaganfall</b>',
category_orders={"stroke": [1,0]},
color_discrete_sequence=['rgb(200, 0, 0)', 'lightgray'],
width=350,
height=350
)
fig.show()
Der Datensatz ist unbalanciert. Nur knapp 5 % sind Daten von Patienten mit Schlaganfall. Da Schlaganfälle vorhergesagt werden sollen, liegt auf dieser Datenimbalance im Folgenden ein besonderes Augenmerk.
stroke = df[df['stroke'] == 1].describe().T
no_stroke = df[df['stroke'] == 0].describe().T
colors = ['#808080']
fig,ax = plt.subplots(nrows = 1,ncols = 2,figsize = (5,5))
plt.subplot(1,2,1)
sns.heatmap(stroke[['mean']],annot = True,cmap = colors,linewidths = 0.4,linecolor = 'black',cbar = False,fmt = '.2f')
plt.title('Schlaganfall')
plt.subplot(1,2,2)
sns.heatmap(no_stroke[['mean']],annot = True,cmap = colors,linewidths = 0.4,linecolor = 'black',cbar = False,fmt = '.2f')
plt.title('kein Schlaganfall')
fig.tight_layout(pad = 0)
bmi ist vergleichsweise schwachavg_glucose_level ist vergleichsweise starkplt.subplots(figsize=(12,5))
sns.heatmap(df.corr(numeric_only=True),annot=True,cmap='RdPu') # 'df.corr()' falls der Parameter 'numeric_only' Probleme macht
plt.title('Korrelation zwischen den Merkmalen')
plt.xticks(rotation=0)
(array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5]), [Text(0.5, 0, 'age'), Text(1.5, 0, 'hypertension'), Text(2.5, 0, 'heart_disease'), Text(3.5, 0, 'avg_glucose_level'), Text(4.5, 0, 'bmi'), Text(5.5, 0, 'stroke')])
stroke